package com.ruoyi.file.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.file.mapper.SysFileMapper;
import com.ruoyi.file.service.ISysFileService;
import com.ruoyi.file.utils.FileUploadUtils;
import com.ruoyi.system.api.domain.SysFile;

import breeze.framework.os.OS;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 文件管理Service业务层处理
 * 
 * @author breeze
 * @date 2022-08-04
 */
@Service
public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> implements ISysFileService {

	@Autowired
	private SysFileMapper sysFileMapper;

	@Override
	public SysFile selectSysFileByFileId(Long fileId) {
		return build(sysFileMapper.selectSysFileByFileId(fileId));
	}

	@Override
	public List<SysFile> selectSysFileList(SysFile sysFile) {
		return build(sysFileMapper.selectSysFileList(sysFile));
	}

	/**
	 * 资源映射路径 前缀
	 */
	@Value("${file.prefix}")
	public String localFilePrefix;

	/**
	 * 域名或本机访问地址
	 */
	@Value("${file.domain}")
	public String domain;

	/**
	 * 上传文件存储在本地的根路径
	 */
	private String localFilePath;

	@Value("${file.path_windows}")
	private String windowsFilePath;
	
	@Value("${file.path_linux}")
	private String linuxFilePath;
	/**
	 * 本地文件上传接口
	 * 
	 * @param file
	 *            上传的文件
	 * @return 访问地址
	 * @throws Exception
	 */
	@Override
	@Transactional
	public SysFile uploadFile(MultipartFile file) throws Exception {

		SysFile sysFile = new SysFile();
		sysFile.setName(file.getOriginalFilename());
		sysFile.setProtocol(ISysFileService.PROTOCOL_LOCAL);
		sysFile.setPath(getLocalFilePath());
		sysFile.setLength(file.getSize());
		sysFile.setCreateTime(new Date());
		sysFile.setCreateBy(SecurityUtils.getUsername());

		if (this.save(sysFile)) {
			String absolute = FileUploadUtils.upload(sysFile, file);
			if (new File(absolute).exists()) {
				sysFile.setUrl(domain + "/file/download/" + sysFile.getFileId());
			} else {
				throw new Exception("上传失败,本地路径不存在指定文件");
			}
		} else {
			throw new Exception("上传失败,保存数据库失败");
		}
		return sysFile;
	}

	@Override
	public void download(long fileId, String downType, HttpServletResponse response) throws IOException {
		SysFile sysFile = this.getById(fileId);
		BufferedInputStream in = null;
		OutputStream out = null;
		if(ISysFileService.PROTOCOL_LOCAL.equals(sysFile.getProtocol())) {
			try {
				String path = getLocalFilePath() + File.separator + sysFile.getFileId();
				File file = new File(path);
				if(!file.exists()) {
					throw new Exception("文件已删除或丢失");
				}
				response.reset();
				if(downType.equalsIgnoreCase("download")) {
					downType = "attachment";
				}
				response.addHeader("Content-Disposition", downType + ";filename=" + URLEncoder.encode(sysFile.getName(),"UTF-8"));
				response.addHeader("Content-Length", "" + file.length());
				//content-type: image/gif
				response.setContentType("application/octet-stream");
				
				 in = new BufferedInputStream(Files.newInputStream(file.toPath()));
				byte[] buf = new byte[1024];
				int len = 0;
				 out = response.getOutputStream();

				while ((len = in.read(buf)) > 0) {
					out.write(buf, 0, len);
				}
				
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				in.close();
				out.close();
				out.flush();
			}
		}
	}

	@Override
	public List<SysFile> selectSysFileListByFileIds(Long[] fileIds) {
		if(null == fileIds || fileIds.length == 0) {
			return null;
		}
		return build(sysFileMapper.selectBatchIds(Arrays.asList(fileIds)));
	}
	
	public List<SysFile> build(List<SysFile> files){
		for (int i = 0; i < files.size(); i++) {
			build(files.get(i));
		}
		return files;
	}
	
	public SysFile build(SysFile file){
		file.setUrl(domain + "/file/download/" + file.getFileId());
		return file;
	}
	
	
	private String getLocalFilePath() {
		if(null == localFilePath) {
			if(OS.isLinux()) {
				localFilePath = linuxFilePath;
			}else {
				localFilePath = windowsFilePath;
			}
		}
		return localFilePath;
	}
}
